	/**
	 * This class wraps the Rejaw REST API (V1) at http://code.google.com/p/rejaw/wiki/API
	 * Results from native API calls are used to create objects witch are dispatched as custom event payloads.
	 * This is not an official release from Rejaw and should not be considered such.
	 * I have no idea what I'm doing and this probably won't work.
	 * I apologize in advance.
	 * 
	 * <p>This class makes use of the JSON serialization class from the as3corelib project found at http://as3corelib.googlecode.com</p>
	 * 
	 * 
	 * @author Bryan Bartow | bryanbartow@gmail.com | http://www.bryanbartow.com
	 * */
package rejaw.api
{	
	import com.adobe.serialization.json.JSON;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	
	import rejaw.api.data.RejawConversation;
	import rejaw.api.data.RejawMessage;
	import rejaw.api.data.RejawUser;
	import rejaw.api.events.RejawEvent;

	public class Rejaw extends EventDispatcher
	{
		//API Call Constants
		//
		//==================
		//Session Calls
		private static const SESSION_CREATE_URL            : String = "http://api.rejaw.com/v1/session/create.json?api_key=@apikey@user@password";
		private static const SESSION_DESTROY_URL           : String = "http://api.rejaw.com/v1/session/destroy.json?session=@session";
		private static const SESSION_VERIFY_URL            : String = "http://api.rejaw.com/v1/session/verify.json?session=@session";
		private static const SESSION_SET_GUESTNAME_URL     : String = "http://api.rejaw.com/v1/session/set_guestname.json?session=@session&guestname=@name";
		
		//Authentication Calls
		private static const AUTH_SIGNIN_URL               : String = "http://api.rejaw.com/v1/auth/signin.json?session=@session&email=@username&password=@password";
		private static const AUTH_SIGNOUT_URL              : String = "http://api.rejaw.com/v1/auth/signout.json?session=@session";

		//User Calls
		private static const USER_GET_INFO_URL             : String = "http://api.rejaw.com/v1/user/get_info.json?session=@session&username=@usernames@properties";
		private static const USER_GET_PROFILE_URL          : String = "http://api.rejaw.com/v1/user/get_profile.json?session=@session&username=@username";
		private static const USER_SET_PROFILE_URL          : String = "http://api.rejaw.com/v1/user/set_profile.json?session=@session@properties";
		private static const USER_GET_INBOX_URL            : String = "http://api.rejaw.com/v1/user/get_inbox.json?session=@session&type=@type@page@per_page@detail@include_replies";
		private static const USER_GET_PEOPLE_URL           : String = "http://api.rejaw.com/v1/user/get_people.json?session=@session&type=@type&username=@username@page";
		private static const USER_ADD_TO_INBOX_URL         : String = "http://api.rejaw.com/v1/user/add_to_inbox.json?session=@session&cid=@cid";
		private static const USER_START_FOLLOWING_URL      : String = "http://api.rejaw.com/v1/user/start_following.json?session=@session&username=@username";
		private static const USER_STOP_FOLLOWING_URL       : String = "http://api.rejaw.com/v1/user/stop_following.json?session=@session&username=@username";
		private static const USER_CATCH_UP_URL             : String = "http://api.rejaw.com/v1/user/catch_up.json?session=@session&type=@type";
		
		//Conversation Calls
		private static const CONVERSATION_GET_INFO_URL     : String = "http://api.rejaw.com/v1/conversation/get_info.json?session=@session&cid=@cid@replies";
		private static const CONVERSATION_GET_REPLIES_URL  : String = "http://api.rejaw.com/v1/conversation/get_replies.json?session=@session&cid=@cid@limit";
		private static const CONVERSATION_SHOUT_URL        : String = "http://api.rejaw.com/v1/conversation/shout.json?session=@session&text=@text";
		private static const CONVERSATION_WHISPER_URL      : String = "http://api.rejaw.com/v1/conversation/whisper.json?session=@session&users=@users&text=@text";
		private static const CONVERSATION_REPLY_URL        : String = "http://api.rejaw.com/v1/conversation/reply.json?session=@session&text=@text&cid=@cid@local";
		private static const CONVERSATION_DELETE_URL       : String = "http://api.rejaw.com/v1/conversation/delete.json?session=@session&cid=@cid";
		private static const CONVERSATION_DELETE_REPLY_URL : String = "http://api.rejaw.com/v1/conversation/delete_reply.json?session=@session&cid=@cid&mid=@mid";
		private static const CONVERSATION_CATCH_UP_URL     : String = "http://api.rejaw.com/v1/conversation/catch_up.json?session=@session&cid=@cid";
		private static const CONVERSATION_MUTE_URL         : String = "http://api.rejaw.com/v1/conversation/mute.json?session=@session&cid=@cid";
		private static const CONVERSATION_UNMUTE_URL       : String = "http://api.rejaw.com/v1/conversation/unmute.json?session=@session&cid=@cid";
		private static const CONVERSATION_FAVORITE_URL     : String = "http://api.rejaw.com/v1/conversation/favorite.json?session=@session&cid=@cid";
		private static const CONVERSATION_UNFAVORITE_URL   : String = "http://api.rejaw.com/v1/conversation/unfavorite.json?session=@session&cid=@cid";
		
		//Subscription Calls
		private static const SUBSCRIPTION_SUBSCRIBE_URL    : String = "http://api.rejaw.com/v1/subscription/subscribe.json?session=@session&topic=@topic";
		private static const SUBSCRIPTION_UNSUBSCRIBE_URL  : String = "http://api.rejaw.com/v1/subscription/unsubscribe.json?session=@session&topic=@topic";
		
		//Event Call
		private static const EVENT_OBSERVE_URL             : String = "http://@random.api.rejaw.com/v1/event/observe.json?session=@session&counter=@counter";
		
		//Timeline Calls
		private static const TIMELINE_PUBLIC_URL           : String = "http://api.rejaw.com/v1/timeline/public.json?session=@session@page@filter";
		private static const TIMELINE_USER_URL             : String = "http://api.rejaw.com/v1/timeline/user.json?session=@session@page@filter@username";
		//======================
		//
		//End API Call Constants
		
		
		
		//Service Name Constants
		//
		//======================
		//Session Service Constants
		private static const SESSION_CREATE            : String = "SessionCreate";
		private static const SESSION_DESTROY           : String = "SessionDestroy";
		private static const SESSION_VERIFY            : String = "SessionVerify";
		private static const SESSION_SET_GUESTNAME     : String = "SessionSetGuestname";
		
		//Authenticaton Service Constants
		private static const AUTH_SIGNIN               : String = "AuthSignin";
		private static const AUTH_SIGNOUT              : String = "AuthSignout";
		
		//User Service Constants
		private static const USER_GET_INFO             : String = "UserGetInfo";
		private static const USER_GET_PROFILE          : String = "UserGetProfile";
		private static const USER_SET_PROFILE          : String = "UserSetProfile";
		private static const USER_GET_INBOX            : String = "UserGetInbox";
		private static const USER_GET_PEOPLE           : String = "UserGetPeople";
		private static const USER_ADD_TO_INBOX         : String = "UserAddToInbox";
		private static const USER_START_FOLLOWING      : String = "UserStartFollowing";
		private static const USER_STOP_FOLLOWING       : String = "UserStopFollowing";
		private static const USER_CATCH_UP             : String = "UserCatchUp";
		
		//Conversation Service Constants
		private static const CONVERSATION_GET_INFO     : String = "ConversationGetInfo";
		private static const CONVERSATION_GET_REPLIES  : String = "ConversationGetReplies";
		private static const CONVERSATION_SHOUT        : String = "ConversationShout";
		private static const CONVERSATION_WHISPER      : String = "ConversationWhisper";
		private static const CONVERSATION_REPLY        : String = "ConversationReply";
		private static const CONVERSATION_DELETE       : String = "ConversationDelet";
		private static const CONVERSATION_DELETE_REPLY : String = "ConversationDeleteReply";
		private static const CONVERSATION_CATCH_UP     : String = "ConversationCatchUp";
		private static const CONVERSATION_MUTE         : String = "ConversationMute";
		private static const CONVERSATION_UNMUTE       : String = "ConversationUnmute";
		private static const CONVERSATION_FAVORITE     : String = "ConversationFavorite";
		private static const CONVERSATION_UNFAVORITE   : String = "ConversationUnfavorite";
		
		//Subscription Service Constants
		private static const SUBSCRIPTION_SUBSCRIBE    : String = "SubscriptionSubscribe";
		private static const SUBSCRIPTION_UNSUBSCRIBE  : String = "SubscriptionUnsubscribe";
		
		//Event Service Constants
		private static const EVENT_OBSERVE             : String = "EventObserve";
		
		//Timline Service Constants
		private static const TIMELINE_PUBLIC           : String = "TimelinePublic";
		private static const TIMELINE_USER             : String = "TimelineUser";
		//==========================
		//
		//End Service Name Constants
		
		
		
		//Private Variables
		//
		//=================
		private var apiCalls : Array = new Array();
		//=================
		//
		//End Private Variables
		
		
		
		//Public Methods
		//
		//==============
		public function Rejaw()
		{
			addAPICalls();
		}
		//
		//Public API Calls
		//
		//================
		
		//Session Calls
		public function sessionCreate( apiKey : String, user : String = null, password : String = null ) : void
		{
			var callLoader : URLLoader = apiCalls[SESSION_CREATE];
			
			var callString : String = SESSION_CREATE_URL.replace( "@apikey", apiKey );
			
			user != null ? callString = callString.replace( "@user", "&user=" + user ) : callString = callString.replace( "@user", "" );
			password != null ? callString = callString.replace( "@password", "&password=" + password ) : callString = callString.replace( "@password", "" );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function sessionDestroy( session : String ) : void
		{
			var callLoader : URLLoader = apiCalls[SESSION_DESTROY];
			
			var callString : String = SESSION_DESTROY_URL.replace( "@session", session );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function sessionVerify( session : String ) : void
		{
			var callLoader : URLLoader = apiCalls[SESSION_VERIFY];
			
			var callString : String = SESSION_VERIFY_URL.replace( "@session", session );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function sessionSetGuestName( session : String, guestName : String ) : void
		{
			var callLoader : URLLoader = apiCalls[SESSION_SET_GUESTNAME];
			
			var callString : String = SESSION_SET_GUESTNAME_URL.replace( "@session", session );
			callString.replace( "@name", guestName );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		//Authentication Calls
		public function authSignIn( session : String, userName : String, password : String ) : void
		{
			var callLoader : URLLoader = apiCalls[AUTH_SIGNIN];
			
			var callString : String = AUTH_SIGNIN_URL.replace( "@session", session );
			callString = callString.replace( "@username", userName );
			callString = callString.replace( "@password", password );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function authSignOut( session : String ) : void
		{
			var callLoader : URLLoader = apiCalls[AUTH_SIGNOUT];
			
			var callString : String = AUTH_SIGNOUT_URL.replace( "@session", session );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		//User Calls
		public function userGetInfo( session : String, users : Array, properties : Array = null ) : void
		{
			var callLoader : URLLoader = apiCalls[USER_GET_INFO];
			
			var callString : String = USER_GET_INFO_URL.replace( "@session", session );
			
			if( users.length == 1 )
			{
				callString = callString.replace( "@usernames", users[0] );
			}
			
			else
			{
				var names : String = "";
				
				for( var i : int = 0; i < users.length - 1; i++ )
				{
					names += users[i] + ",";
				}
				
				names += users[users.length - 1];
				
				callString = callString.replace( "@usernames", names );
			}
			
			
			if( properties != null )
			{
				if( properties.length == 1 )
				{
					callString = callString.replace( "@properties", properties[0] );
				}
			
				else
				{
					var props : String = "";
					
					for( var j : int = 0; j < properties.length - 1; j++ )
					{
						props += properties[j] + ",";
					}
					
					props += properties[properties.length - 1]
					
					callString = callString.replace( "@properties", props );
				}
			}
			
			else
			{
				callString = callString.replace( "@properties", "" );
			}
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function userGetProfile( session : String, userName : String ) : void
		{
			var callLoader : URLLoader = apiCalls[USER_GET_PROFILE];
			
			var callString : String = USER_GET_PROFILE_URL.replace( "@session", session );
			callString = callString.replace( "@username", userName );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function userSetProfile( session : String, props : Object ) : void
		{
			var callLoader : URLLoader = apiCalls[USER_SET_PROFILE];
			
			var callString : String = USER_SET_PROFILE_URL.replace( "@session", session );
			
			var s : String = "";
			for( var prop : String in props )
			{
				s += "&" + prop + "=" + props[prop];
			}
			
			callString = callString.replace( "@properties", s );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function userGetInbox( session : String, type : String, page : String = null, per_page : String = null, detail : String = null, include_replies : String = null ) : void
		{
			var callLoader : URLLoader = apiCalls[USER_GET_INBOX];
			
			var callString : String = USER_GET_INBOX_URL.replace( "@session", session );			
			callString = callString.replace( "@type", type );
			page != null ? callString = callString.replace( "@page", "&page=" + page ) : callString = callString.replace( "@page", "" );
			per_page != null ? callString = callString.replace( "@per_page", "&per_page=" + per_page ) : callString = callString.replace( "@per_page", "" );
			detail != null ? callString = callString.replace( "@detail", "&detail=" + per_page ) : callString = callString.replace( "@detail", "" );
			include_replies != null ? callString = callString.replace( "@include_replies", "&include_replies=" + per_page ) : callString = callString.replace( "@include_replies", "" );
			
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function userGetPeople( session : String, type : String, userName : String, page : String = null ) : void
		{
			var callLoader : URLLoader = apiCalls[USER_GET_PEOPLE];
			
			var callString : String = USER_GET_PEOPLE_URL.replace( "@session", session );			
			callString = callString.replace( "@type", type );
			callString = callString.replace( "@username", userName );
			page != null ? callString = callString.replace( "@page", "&page=" + page ) : callString = callString.replace( "@page", "" );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function userAddToInbox( session : String, cid : String ) : void
		{
			var callLoader : URLLoader = apiCalls[USER_ADD_TO_INBOX];
			
			var callString : String = USER_ADD_TO_INBOX_URL.replace( "@session", session );			
			callString = callString.replace( "@cid", cid );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function userStartFollowing( session : String, userName : String ) : void
		{
			var callLoader : URLLoader = apiCalls[USER_START_FOLLOWING];
			
			var callString : String = USER_START_FOLLOWING_URL.replace( "@session", session );			
			callString = callString.replace( "@username", userName );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function userStopFollowing( session : String, userName : String ) : void
		{
			var callLoader : URLLoader = apiCalls[USER_STOP_FOLLOWING];
			
			var callString : String = USER_STOP_FOLLOWING_URL.replace( "@session", session );			
			callString = callString.replace( "@username", userName );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function userCatchUp( session : String, type : String ) : void
		{
			var callLoader : URLLoader = apiCalls[USER_CATCH_UP];
			
			var callString : String = USER_CATCH_UP_URL.replace( "@session", session );			
			callString = callString.replace( "@type", type );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		//Conversation Calls
		public function conversationGetInfo( session : String, cids : Array, replies : Number = NaN ) : void
		{
			var callLoader : URLLoader = apiCalls[CONVERSATION_GET_INFO];
			
			var callString : String = CONVERSATION_GET_INFO_URL.replace( "@session", session );			
			
			var s : String = "";
			if( cids.length > 1 )
			{
				for each( var cid : String in cids )
				{
					s += "," + cid;
				}
			}
			
			else
			{
				s = cids[0];
			}
			
			callString = callString.replace( "@cid", s );
			
			isNaN( replies ) == false ? callString = callString.replace( "@replies", "&include_replies=" + replies ) : callString = callString.replace( "@replies", "" );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function conversationGetReplies( session : String, cid : String, limit : Number = NaN ) : void
		{
			var callLoader : URLLoader = apiCalls[CONVERSATION_GET_REPLIES];
			
			var callString : String = CONVERSATION_GET_REPLIES_URL.replace( "@session", session );			
			callString = callString.replace( "@cid", cid );
			
			isNaN( limit ) == false ? callString = callString.replace( "@limit", "&limit=" + limit ) : callString = callString.replace( "@limit", "" );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function conversationShout( session : String, text : String ) : void
		{
			var callLoader : URLLoader = apiCalls[CONVERSATION_SHOUT];
			
			var callString : String = CONVERSATION_SHOUT_URL.replace( "@session", session );			
			callString = callString.replace( "@text", text );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function conversationWhisper( session : String, users : Array, text : String ) : void
		{
			var callLoader : URLLoader = apiCalls[CONVERSATION_WHISPER];
			
			var callString : String = CONVERSATION_WHISPER_URL.replace( "@session", session );			
			callString = callString.replace( "@text", text );
			
			var s : String = "";
			if( users.length > 1 )
			{
				for( var i : int = 0; i < users.length; i++ )
				{
					if( i == 0 )
					{
						s += users[i];
					}
					
					else
					{
						s += "," + users[i];
					}
				}
			}
			
			else
			{
				s = users[0];
			}
			
			callString = callString.replace( "@users", s );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function conversationReply( session : String, cid : String, text : String, local_id : String = null ) : void
		{
			var callLoader : URLLoader = apiCalls[CONVERSATION_REPLY];
			
			var callString : String = CONVERSATION_REPLY_URL.replace( "@session", session );			
			callString = callString.replace( "@cid", cid );
			callString = callString.replace( "@text", text );
			
			local_id != null ? callString = callString.replace( "@local", "&local_id=" + local_id ) : callString = callString.replace( "@local", "" );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function conversationDelete( session : String, cid : String ) : void
		{
			var callLoader : URLLoader = apiCalls[CONVERSATION_DELETE];
			
			var callString : String = CONVERSATION_DELETE_URL.replace( "@session", session );			
			callString = callString.replace( "@cid", cid );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function conversationDeleteReply( session : String, cid : String, mid : String ) : void
		{
			var callLoader : URLLoader = apiCalls[CONVERSATION_DELETE_REPLY];
			
			var callString : String = CONVERSATION_DELETE_REPLY_URL.replace( "@session", session );			
			callString = callString.replace( "@cid", cid );
			callString = callString.replace( "@mid", mid );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function conversationCatchUp( session : String, cids : Array ) : void
		{
			var callLoader : URLLoader = apiCalls[CONVERSATION_CATCH_UP];
			
			var callString : String = CONVERSATION_CATCH_UP_URL.replace( "@session", session );			
			
			var s : String = "";
			if( cids.length > 1 )
			{
				for( var i : int = 0; i < cids.length; i++ )
				{
					if( i == 0 )
					{
						s += cids[i];
					}
					
					else
					{
						s += "," + cids[i];
					}
				}
			}
			
			else
			{
				s = cids[0];
			}
			
			callString = callString.replace( "@cid", s );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function conversationMute( session : String, cid : String ) : void
		{
			var callLoader : URLLoader = apiCalls[CONVERSATION_MUTE];
			
			var callString : String = CONVERSATION_MUTE_URL.replace( "@session", session );			
			callString = callString.replace( "@cid", cid );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function conversationUnmute( session : String, cid : String ) : void
		{
			var callLoader : URLLoader = apiCalls[CONVERSATION_UNMUTE];
			
			var callString : String = CONVERSATION_UNMUTE_URL.replace( "@session", session );			
			callString = callString.replace( "@cid", cid );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function conversationFavorite( session : String, cid : String ) : void
		{
			var callLoader : URLLoader = apiCalls[CONVERSATION_FAVORITE];
			
			var callString : String = CONVERSATION_FAVORITE_URL.replace( "@session", session );
			callString = callString.replace( "@cid", cid );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function conversationUnfavorite( session : String, cid : String ) : void
		{
			var callLoader : URLLoader = apiCalls[CONVERSATION_UNFAVORITE];
			
			var callString : String = CONVERSATION_UNFAVORITE_URL.replace( "@session", session );
			callString = callString.replace( "@cid", cid );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		//Subscription Calls
		public function subscriptionSubscribe( session : String, topic : Array ) : void
		{
			var callLoader : URLLoader = apiCalls[SUBSCRIPTION_SUBSCRIBE];
			
			var callString : String = SUBSCRIPTION_SUBSCRIBE_URL.replace( "@session", session );			
			
			if( topic.length == 1 )
			{
				callString = callString.replace( "@topic", topic[0] );
			}
			
			else
			{
				var topics : String = "";
				
				for( var i : int = 0; i < topic.length - 1; i++ )
				{
					topics += topic[i] + ",";
				}
				
				topics += topic[topic.length - 1];
				
				callString = callString.replace( "@topic", topics );
			}
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function subscriptionUnsubscribe( session : String, topic : Array ) : void
		{
			var callLoader : URLLoader = apiCalls[SUBSCRIPTION_SUBSCRIBE];
			
			var callString : String = SUBSCRIPTION_SUBSCRIBE_URL.replace( "@session", session );			
			
			if( topic.length == 1 )
			{
				callString = callString.replace( "@topic", topic[0] );
			}
			
			else
			{
				var topics : String = "";
				
				for( var i : int = 0; i < topic.length - 1; i++ )
				{
					topics += topic[i] + ",";
				}
				
				topics += topic[topic.length - 1];
				
				callString = callString.replace( "@topic", topics );
			}
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		//Event Call
		public function eventObserve( session : String, random : String, counter : String ) : void
		{
			var callLoader : URLLoader = apiCalls[EVENT_OBSERVE];
			
			var callString : String = EVENT_OBSERVE_URL.replace( "@session", session );			
			callString = callString.replace( "@random", random );
			callString = callString.replace( "@counter", counter);
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		//Timeline Calls
		public function timelinePublic( session : String, page : String = null, filter : String = null ) : void
		{
			var callLoader : URLLoader = apiCalls[TIMELINE_PUBLIC];
			
			var callString : String = TIMELINE_PUBLIC_URL.replace( "@session", session );			
			page != null ? callString = callString.replace( "@page", "&page=" + page ) : callString = callString.replace( "@page", "" );
			filter != null ? callString = callString.replace( "@filter", "&filter=" + filter ) : callString = callString.replace( "@filter", "" );
			
			callLoader.load( new URLRequest( callString ) );
		}
		
		public function timelineUser( session : String, username : String = null, page : String = null, filter : String = null ) : void
		{
			var callLoader : URLLoader = apiCalls[TIMELINE_USER];
			
			var callString : String = TIMELINE_USER_URL.replace( "@session", session );			
			page != null ? callString = callString.replace( "@page", "&page=" + page ) : callString = callString.replace( "@page", "" );
			filter != null ? callString = callString.replace( "@filter", "&filter=" + filter ) : callString = callString.replace( "@filter", "" );
			username != null ? callString = callString.replace( "@username", "&username=" + username ) : callString = callString.replace( "@username", "" );
			
			callLoader.load( new URLRequest( callString ) );
		}
		//====================
		//
		//End Public API Calls
		
		//==================
		//
		//End Public Methods
		
		
		
		//Private Methods
		//
		//===============
		
		private function addAPICalls() : void
		{
			//We'll add a custom URLLoader for each API call to the apiCalls array
			//As far as I can tell, all Rejaw API calls can share the same error handling
			
			//Add Session API Calls
			addAPICall( SESSION_CREATE, onSessionCreate );
			addAPICall( SESSION_DESTROY, onSessionDestroy );
			addAPICall( SESSION_VERIFY, onSessionVerify );
			addAPICall( SESSION_SET_GUESTNAME, onSessionSetGuestname );
			
			//Add Authentication API Calls
			addAPICall( AUTH_SIGNIN, onAuthSignin );
			addAPICall( AUTH_SIGNOUT, onAuthSignout );
			
			
			//Add User API Calls
			addAPICall( USER_GET_INFO, onUserGetInfo );
			addAPICall( USER_GET_PROFILE, onUserGetProfile );
			addAPICall( USER_SET_PROFILE, onUserSetProfile );
			addAPICall( USER_GET_INBOX, onUserGetInbox );
			addAPICall( USER_GET_PEOPLE, onUserGetPeople );
			addAPICall( USER_ADD_TO_INBOX, onUserAddToInbox );
			addAPICall( USER_START_FOLLOWING, onUserStartFollowing );
			addAPICall( USER_STOP_FOLLOWING, onUserStopFollowing );
			addAPICall( USER_CATCH_UP, onUserCatchUp );
			
			//Add Conversation API Calls
			addAPICall( CONVERSATION_GET_INFO, onConversationGetInfo );
			addAPICall( CONVERSATION_GET_REPLIES, onConversationGetReplies );
			addAPICall( CONVERSATION_SHOUT, onConversationShout );
			addAPICall( CONVERSATION_WHISPER, onConversationWhisper );
			addAPICall( CONVERSATION_REPLY, onConversationReply );
			addAPICall( CONVERSATION_DELETE, onConversationDelete );
			addAPICall( CONVERSATION_DELETE_REPLY, onConversationDeleteReply );
			addAPICall( CONVERSATION_CATCH_UP, onConversationCatchUp );
			addAPICall( CONVERSATION_MUTE, onConversationMute );
			addAPICall( CONVERSATION_UNMUTE, onConversationUnmute );
			addAPICall( CONVERSATION_FAVORITE, onConversationFavorite );
			addAPICall( CONVERSATION_UNFAVORITE, onConversationUnfavorite );
			
			//Add Subscription API Calls
			addAPICall( SUBSCRIPTION_SUBSCRIBE, onSubscriptionSubscribe );
			addAPICall( SUBSCRIPTION_UNSUBSCRIBE, onSubscriptionUnsubscribe );
			
			//Add Event API Call
			addAPICall( EVENT_OBSERVE, onEventObserve );
			
			//Add Timeline API Calls
			addAPICall( TIMELINE_PUBLIC, onTimelinePublic );
			addAPICall( TIMELINE_USER, onTimelineUser );
			
		}
		
		//Private (Internal) Rejaw Event Handlers
		//
		//=========================================
		
		//Session Event Handlers
		private function onSessionCreate( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.SESSION_CREATE );
			
			rejawEvent.data = JSON.decode( apiCalls[SESSION_CREATE].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onSessionDestroy( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.SESSION_DESTROY );
			
			rejawEvent.data = JSON.decode( apiCalls[SESSION_DESTROY].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onSessionVerify( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.SESSION_VERIFY );
			
			rejawEvent.data = JSON.decode( apiCalls[SESSION_VERIFY].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onSessionSetGuestname( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.SESSION_SET_GUESTNAME );
			
			rejawEvent.data = JSON.decode( apiCalls[SESSION_SET_GUESTNAME].data );
			
			dispatchEvent( rejawEvent );
		}
		
		//Authentication Event Handlers
		private function onAuthSignin( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.AUTH_SIGNIN );
			
			rejawEvent.data = JSON.decode( apiCalls[AUTH_SIGNIN].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onAuthSignout( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.AUTH_SIGNOUT );
			
			rejawEvent.data = JSON.decode( apiCalls[AUTH_SIGNOUT].data );
			
			dispatchEvent( rejawEvent );
		}
		
		//User Event Handlers
		private function onUserGetInfo( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.USER_GET_INFO );
			
			rejawEvent.data = JSON.decode( apiCalls[USER_GET_INFO].data );
			
			for( var i : int = 0; i < rejawEvent.data.users.length; i++ )
			{
				var user : RejawUser = new RejawUser( rejawEvent.data.users[i] );
				rejawEvent.data.users.splice( i, 1, user );
			}
			
			dispatchEvent( rejawEvent );
		}
		
		private function onUserGetProfile( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.USER_GET_PROFILE );
			
			rejawEvent.data = JSON.decode( apiCalls[USER_GET_PROFILE].data );
			
			var user : RejawUser = new RejawUser( rejawEvent.data.user );
			rejawEvent.data.user = user;
			
			dispatchEvent( rejawEvent );
		}
		
		private function onUserSetProfile( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.USER_SET_PROFILE );
			
			rejawEvent.data = JSON.decode( apiCalls[USER_SET_PROFILE].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onUserGetInbox( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.USER_GET_INBOX);
			
			rejawEvent.data = JSON.decode( apiCalls[USER_GET_INBOX].data );
			
			if( !( rejawEvent.data.conversations[0] is String ) )
			{
				for( var i : int = 0; i < rejawEvent.data.conversations.length; i++ )
				{
					var conversation : RejawConversation = new RejawConversation( rejawEvent.data.conversations[i] );
					rejawEvent.data.conversations.splice( i, 1, conversation );
				}
			}
			
			dispatchEvent( rejawEvent );
		}
		
		private function onUserGetPeople( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.USER_GET_PEOPLE);
			
			rejawEvent.data = JSON.decode( apiCalls[USER_GET_PEOPLE].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onUserAddToInbox( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.USER_ADD_TO_INBOX );
			
			rejawEvent.data = JSON.decode( apiCalls[USER_ADD_TO_INBOX].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onUserStartFollowing( evt : Event ) : void
		{
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.USER_START_FOLLOWING );
			
			rejawEvent.data = JSON.decode( apiCalls[USER_START_FOLLOWING].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onUserStopFollowing( evt : Event ) : void
		{
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.USER_STOP_FOLLOWING );
			
			rejawEvent.data = JSON.decode( apiCalls[USER_STOP_FOLLOWING].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onUserCatchUp( evt : Event ) : void
		{
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.USER_CATCH_UP );
			
			rejawEvent.data = JSON.decode( apiCalls[USER_CATCH_UP].data );
			
			dispatchEvent( rejawEvent );
		}
		
		//Conversation Event Handlers
		private function onConversationGetInfo( evt : Event ) : void
		{
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.CONVERSATION_GET_INFO );
			
			rejawEvent.data = JSON.decode( apiCalls[CONVERSATION_GET_INFO].data );
			
			for( var i : int = 0; i < rejawEvent.data.conversations.length; i++ )
			{
				var conversation : RejawConversation = new RejawConversation( rejawEvent.data.conversations[i] );
				rejawEvent.data.conversations.splice( i, 1, conversation );
			}
			
			dispatchEvent( rejawEvent );
		}
		
		private function onConversationGetReplies( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.CONVERSATION_GET_REPLIES );
			
			rejawEvent.data = JSON.decode( apiCalls[CONVERSATION_GET_REPLIES].data );
			
			for( var i : int = 0; i < rejawEvent.data.messages.length; i++ )
			{
				var message : RejawMessage = new RejawMessage( rejawEvent.data.messages[i] );
				rejawEvent.data.messages.splice( i, 1, message );
			}
			
			dispatchEvent( rejawEvent );
		}
		
		private function onConversationShout( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.CONVERSATION_SHOUT );
			
			rejawEvent.data = JSON.decode( apiCalls[CONVERSATION_SHOUT].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onConversationWhisper( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.CONVERSATION_WHISPER );
			
			rejawEvent.data = JSON.decode( apiCalls[CONVERSATION_WHISPER].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onConversationReply( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.CONVERSATION_REPLY );
			
			rejawEvent.data = JSON.decode( apiCalls[CONVERSATION_REPLY].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onConversationDelete( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.CONVERSATION_DELETE );
			
			rejawEvent.data = JSON.decode( apiCalls[CONVERSATION_DELETE].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onConversationDeleteReply( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.CONVERSATION_DELETE_REPLY );
			
			rejawEvent.data = JSON.decode( apiCalls[CONVERSATION_DELETE_REPLY].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onConversationCatchUp( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.CONVERSATION_CATCH_UP );
			
			rejawEvent.data = JSON.decode( apiCalls[CONVERSATION_CATCH_UP].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onConversationMute( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.CONVERSATION_MUTE );
			
			rejawEvent.data = JSON.decode( apiCalls[CONVERSATION_MUTE].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onConversationUnmute( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.CONVERSATION_UNMUTE );
			
			rejawEvent.data = JSON.decode( apiCalls[CONVERSATION_UNMUTE].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onConversationFavorite( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.CONVERSATION_FAVORITE );
			
			rejawEvent.data = JSON.decode( apiCalls[CONVERSATION_FAVORITE].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onConversationUnfavorite( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.CONVERSATION_UNFAVORITE );
			
			rejawEvent.data = JSON.decode( apiCalls[CONVERSATION_UNFAVORITE].data );
			
			dispatchEvent( rejawEvent );
		}
		
		//Subscription Event Handlers
		private function onSubscriptionSubscribe( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.SUBSCRIPTION_SUBSCRIBE );
			
			rejawEvent.data = JSON.decode( apiCalls[SUBSCRIPTION_SUBSCRIBE].data );
			
			dispatchEvent( rejawEvent );
		}
		
		private function onSubscriptionUnsubscribe( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.SUBSCRIPTION_UNSUBSCRIBE );
			
			rejawEvent.data = JSON.decode( apiCalls[SUBSCRIPTION_UNSUBSCRIBE].data );
			
			dispatchEvent( rejawEvent );
		}
		
		
		//Event Event Handler
		private function onEventObserve( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.EVENT_OBSERVE );
			
			rejawEvent.data = JSON.decode( apiCalls[EVENT_OBSERVE].data );
			
			dispatchEvent( rejawEvent );
		}
		
		//Timeline Event Handlers
		private function onTimelinePublic( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.TIMELINE_PUBLIC );
			
			rejawEvent.data = JSON.decode( apiCalls[TIMELINE_PUBLIC].data );
			
			for( var i : int = 0; i < rejawEvent.data.messages.length; i++ )
			{
				var message : RejawMessage = new RejawMessage( rejawEvent.data.messages[i] );
				rejawEvent.data.messages.splice( i, 1, message );
			}
			
			dispatchEvent( rejawEvent );
		}
		
		private function onTimelineUser( evt : Event ) : void
		{			
			var rejawEvent : RejawEvent = new RejawEvent( RejawEvent.TIMELINE_USER);
			
			rejawEvent.data = JSON.decode( apiCalls[TIMELINE_USER].data );
			
			for( var i : int = 0; i < rejawEvent.data.messages.length; i++ )
			{
				var message : RejawMessage = new RejawMessage( rejawEvent.data.messages[i] );
				rejawEvent.data.messages.splice( i, 1, message );
			}
			
			dispatchEvent( rejawEvent );
		}
		
		private function addAPICall( serviceName : String, completeHandler : Function ) : void
		{
			var apiCallLoader : URLLoader = new URLLoader();

			apiCallLoader.addEventListener( Event.COMPLETE, completeHandler );
			apiCallLoader.addEventListener( IOErrorEvent.IO_ERROR, onErrorEvent );
			apiCallLoader.addEventListener( SecurityErrorEvent.SECURITY_ERROR, onErrorEvent );
			apiCallLoader.addEventListener( HTTPStatusEvent.HTTP_STATUS, onHTTPStatusEvent );
			apiCallLoader.addEventListener( HTTPStatusEvent.HTTP_RESPONSE_STATUS, onHTTPStatusEvent );
			
			apiCalls[serviceName] = apiCallLoader;
		}
		
		private function onErrorEvent( evt : IOErrorEvent ) : void
		{
			trace( "ERROR: " + evt.text );
		}
		
		private function onHTTPStatusEvent( evt : HTTPStatusEvent ) : void
		{
			trace( "STATUS: " + evt.status );
		}
	}
}